package de.akabahn.ebd.stw.zdxfc.prs.tco.elemente;

import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.BIT0;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.BIT10;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.BIT2;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.BIT4;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.BIT6;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.BIT8;
import static de.akabahn.ebd.stw.zdxfc.prs.tco.ZDXFCTcoConstants.WEICHENMELDER_AKTIV_FARBE;
import static de.akabahn.ebd.stw.zdxfc.prs.tco.ZDXFCTcoConstants.WEICHENMELDER_AUS_FARBE;
import static de.akabahn.ebd.stw.zdxfc.prs.tco.ZDXFCTcoConstants.WEICHENMELDER_BESETZT_FARBE;
import static de.akabahn.ebd.stw.zdxfc.prs.tco.ZDXFCTcoConstants.WEICHE_FARBE;

import java.awt.Color;
import java.awt.Graphics;

/**
 * Implementierung der <code>Weichenmelder</code>.<br>
 * <br>
 * Bitcodierung des Weichen-Gleismelders<br>
 * <pre>
 * BIT11 BIT10 BIT9 BIT8 BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0  BEDEUTUNG 
 *     0     0    0    0    0    0    0    0    0    0    0    0  AUS
 *     0     0    0    0    0    0    0    0    0    0    0    1  SPITZE WEISS AN
 *     0     0    0    0    0    0    0    0    0    0    1    0  SPITZE WEISS BLINKT
 *     0     0    0    0    0    0    0    0    0    1    0    0  SPITZE ROT AN
 *     0     0    0    0    0    0    0    0    1    0    0    0  SPITZE ROT BLINKT
 *     0     0    0    0    0    0    0    1    0    0    0    0  RECHTS WEISS AN
 *     0     0    0    0    0    0    1    0    0    0    0    0  RECHTS WEISS BLINKT
 *     0     0    0    0    0    1    0    0    0    0    0    0  RECHTS ROT AN
 *     0     0    0    0    1    0    0    0    0    0    0    0  RECHTS ROT BLINKT
 *     0     0    0    1    0    0    0    0    0    0    0    0  LINKS WEISS AN
 *     0     0    1    0    0    0    0    0    0    0    0    0  LINKS WEISS BLINKT
 *     0     1    0    0    0    0    0    0    0    0    0    0  LINKS ROT AN
 *     1     0    0    0    0    0    0    0    0    0    0    0  LINKS ROT BLINKT
 * </pre>
 * <br>
 * Bitcodierung des Weichen-Lagemelders<br>
 * <pre>
 * BIT3 BIT2 BIT1 BIT0  BEDEUTUNG
 *    0    0    0    0  AUS
 *    0    0    0    1  RECHTS WEISS AN
 *    0    0    1    0  RECHTS WEISS BLINKT
 *    0    1    0    0  LINKS WEISS AN
 *    1    0    0    0  LINKS WEISS BLINKT
 * </pre>
 * 
 * @author Peter Eimann
 * @since 1.0
 * @version 1.1
 */
public abstract class Weiche {

	private String[] id;
	
	protected int ausleuchtungGleismelder;
	protected int ausleuchtungLagemelder;
	protected boolean highlightSpitze;
	protected boolean highlightRechts;
	protected boolean highlightLinks;

	/**
	 * Initialisieurung der Weiche
	 * 
	 * @param id Eindeutige IDs (Gleismelder und Lagemelder) der Weiche
	 */
	public Weiche(String[] id) {
		this.id = id;
	}
	
	/**
	 * Gibt den bitcodierten Wert der Ausleuchtung des Gleismelders zurueck
	 * 
	 * @return Die Ausleuchtung
	 */
	public int getAusleuchtungGleismelder() {
		return ausleuchtungGleismelder;
	}

	/**
	 * Setzt den bitcodierten Wert der Ausleuchtung des Gleismelders
	 * 
	 * @param ausleuchtungGleismelder Die Ausleuchtung
	 */
	public void setAusleuchtungGleismelder(int ausleuchtungGleismelder) {
		this.ausleuchtungGleismelder = ausleuchtungGleismelder;
	}

	/**
	 * Gibt den bitcodierten Wert der Ausleuchtung des Lagemelders zurueck
	 * 
	 * @return Die Ausleuchtung
	 */
	public int getAusleuchtungLagemelder() {
		return ausleuchtungLagemelder;
	}

	/**
	 * Setzt den bitcodierten Wert der Ausleuchtung des Lagemelders
	 * 
	 * @param ausleuchtungLagemelder Die Ausleuchtung
	 */
	public void setAusleuchtungLagemelder(int ausleuchtungLagemelder) {
		this.ausleuchtungLagemelder = ausleuchtungLagemelder;
	}

	/**
	 * Gibt die ID des Elements an
	 * 
	 * @return die ID
	 */
	public String[] getId() {
		return id;
	}

	/**
	 * Zeichnen der Weiche mit den Farben des Ausleuchtungszustands der Gleis- und
	 * Lagemelder.
	 * 
	 * @param g Der Grafik-Kontext
	 * @see #paintWeiche(Graphics)
	 * @see #paintMelderSpitze(Graphics)
	 * @see #paintMelderRechts(Graphics)
	 * @see #paintMelderLinks(Graphics)
	 */
	public void paint(Graphics g) {
		g.setColor(WEICHE_FARBE);
		paintWeiche(g);
		g.setColor(getColorMelderSpitze());
		paintMelderSpitze(g);
		g.setColor(getColorMelderRechts());
		paintMelderRechts(g);
		g.setColor(getColorMelderLinks());
		paintMelderLinks(g);
	}
	
	/**
	 * Zeichnen der Weiche ohne Ausleuchtung (muss in der konkreten Weichenklasse implementiert werden)
	 * 
	 * @param g Der Grafik-Kontext
	 */
	protected void paintWeiche(Graphics g) {
	}
	
	/**
	 * Zeichnen der Ausleuchtung der Weichenspitze (muss in der konkreten Weichenklasse implementiert werden)
	 * 
	 * @param g Der Grafik-Kontext
	 */
	protected void paintMelderSpitze(Graphics g) {
	}
	
	/**
	 * Zeichnen der Ausleuchtung der rechte Seite der Weiche (muss in der konkreten Weichenklasse implementiert werden)
	 * 
	 * @param g Der Grafik-Kontext
	 */
	protected void paintMelderRechts(Graphics g) {
	}
	
	/**
	 * Zeichnen der Ausleuchtung der linken Seite der Weiche (muss in der konkreten Weichenklasse implementiert werden)
	 * 
	 * @param g Der Grafik-Kontext
	 */
	protected void paintMelderLinks(Graphics g) {
	}
	
	/**
	 * Gibt die Farbe der Weichenspitze aufgrund der aktuellen Ausleuchtung (besetzt, aktiv, frei)
	 * zurueck.
	 * 
	 * @return Die Farbe der Weichenspitze
	 */
	private Color getColorMelderSpitze() {
		if ((ausleuchtungGleismelder & BIT2) == BIT2) {
			highlightSpitze = true;
			return WEICHENMELDER_BESETZT_FARBE;
		} else if ((ausleuchtungGleismelder & BIT0) == BIT0) {
			highlightSpitze = true;
			return WEICHENMELDER_AKTIV_FARBE;
		} else {
			highlightSpitze = false;
			return WEICHENMELDER_AUS_FARBE;
		}
	}
	
	/**
	 * Gibt die Farbe der rechten Seite der Weiche aufgrund der aktuellen Ausleuchtung
	 * (besetzt, aktiv, zeige Lagemelder, frei) zurueck.
	 * 
	 * @return Die Farbe der Weichenspitze
	 */
	private Color getColorMelderRechts() {
		if ((ausleuchtungGleismelder & BIT6) == BIT6) {
			highlightRechts = true;
			return WEICHENMELDER_BESETZT_FARBE;
		} else if ((ausleuchtungGleismelder & BIT4) == BIT4) {
			highlightRechts = true;
			return WEICHENMELDER_AKTIV_FARBE;
		} else if ((ausleuchtungLagemelder & BIT0) == BIT0) {
			highlightRechts = true;
			return WEICHENMELDER_AKTIV_FARBE;
		} else {
			highlightRechts = false;
			return WEICHENMELDER_AUS_FARBE;
		}
	}
	
	/**
	 * Gibt die Farbe der linken Seite der Weiche aufgrund der aktuellen Ausleuchtung
	 * (besetzt, aktiv, zeige Lagemelder, frei) zurueck.
	 * Besetzte oder aktive Weichen werden zur besseren Erkennbarkeit etwas breiter gezeichnet (hervorgehoben).
	 * 
	 * @return Die Farbe der Weichenspitze
	 */
	private Color getColorMelderLinks() {
		if ((ausleuchtungGleismelder & BIT10) == BIT10) {
			highlightLinks = true;
			return WEICHENMELDER_BESETZT_FARBE;
		} else if ((ausleuchtungGleismelder & BIT8) == BIT8) {
			highlightLinks = true;
			return WEICHENMELDER_AKTIV_FARBE;
		} else if ((ausleuchtungLagemelder & BIT2) == BIT2) {
			highlightLinks = true;
			return WEICHENMELDER_AKTIV_FARBE;
		} else {
			highlightLinks = false;
			return WEICHENMELDER_AUS_FARBE;
		}
	}
}
